package cn.kinoko.service.manga.event;

import cn.kinoko.model.manga.entity.MangaMetrics;
import cn.kinoko.model.manga.event.MangaMetricsEventArgs;
import cn.kinoko.service.common.event.EventHandler;
import cn.kinoko.service.common.event.EventTopic;
import cn.kinoko.service.common.event.EventTopicEnum;
import cn.kinoko.service.common.event.component.Event;
import cn.kinoko.service.manga.MangaMetricsService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 漫画浏览事件消费者
 *
 * @author kk
 */
@EventTopic(EventTopicEnum.MANGA_METRICS_PLUS)
@Component
public class MangaViewPlusEvent implements EventHandler {

    @Resource
    private MangaMetricsService mangaMetricsService;

    /**
     * 事件存储（消费）
     *
     * @param events 事件
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void eventHandle(List<Event> events) {
        // 抽出事件参数，并压缩
        List<MangaMetricsEventArgs> argsList = events.stream()
                .map(event -> (MangaMetricsEventArgs) event.getEventParams())
                // 按漫画、时间、类型分组
                .collect(Collectors.groupingBy(args -> args.getMangaId() + "_" + args.getWeek() + "_" + args.getType())).values()
                // 压缩事件，同组合并为一个
                .stream().map(argsGroup -> {
                    // 取第一个作为最终入库实例
                    MangaMetricsEventArgs finalArgs = argsGroup.getFirst();
                    // 最终的数量变化
                    long finalCount = 0;
                    for (MangaMetricsEventArgs args : argsGroup) {
                        finalCount += args.getCount();
                    }
                    finalArgs.setCount(finalCount);
                    return finalArgs;
                }).toList();
        List<Long> mangaIdList = argsList.stream().map(MangaMetricsEventArgs::getMangaId).toList();
        // 查询已有的浏览记录，按漫画分组
        Map<Long, Map<Integer, List<MangaMetrics>>> mangaMetricsMap = mangaMetricsService.lambdaQuery().in(MangaMetrics::getMangaId, mangaIdList).list().stream()
                .collect(Collectors.groupingBy(MangaMetrics::getMangaId, Collectors.groupingBy(MangaMetrics::getWeek)));
        // 存在浏览量的 +1/-1，不存在的创建记录
        List<MangaMetrics> mangaMetricsList = argsList.stream().map(args -> {
            Map<Integer, List<MangaMetrics>> weekMap = mangaMetricsMap.get(args.getMangaId());
            // 不存在创建浏览记录
            if (weekMap == null || weekMap.get(args.getWeek()) == null) {
                MangaMetrics metrics = new MangaMetrics();
                metrics.setMangaId(args.getMangaId());
                metrics.setYear(args.getYear());
                metrics.setMonth(args.getMonth());
                metrics.setWeek(args.getWeek());
                // 根据类型进行指标量 + 1
                switch (args.getType()) {
                    case VIEW -> metrics.setViewCount(args.getCount());
                    case LIKE -> metrics.setLikeCount(args.getCount());
                }
                return metrics;
            }
            List<MangaMetrics> metricsList = weekMap.get(args.getWeek());
            // 因为做了唯一key，所以获取第一个即可
            MangaMetrics metrics = metricsList.getFirst();
            // 根据类型进行指标量 +1/-1
            switch (args.getType()) {
                case VIEW -> metrics.setViewCount(metrics.getViewCount() + args.getCount());
                case LIKE -> metrics.setLikeCount(metrics.getLikeCount() + args.getCount());
            }
            return metrics;
        }).toList();
        // 批量新增或更新
        mangaMetricsService.saveOrUpdateBatch(mangaMetricsList);
    }
}
